using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Threading;
using Microsoft.Data.Extensions;
using MvcCms.Data.Entities;
using MvcCms.Data.Code;
using Devart.Data.PostgreSql;

namespace MvcCms.Data
{
    internal class Search
    {
        #region Constructors
        private static readonly CultureInfo CultureInfo = Thread.CurrentThread.CurrentCulture;
        private static readonly TextInfo TextInfo = CultureInfo.TextInfo;
        private static string _term;
        private readonly MvcCmsEntities _entities;


        private string _hyphenwords = "";
        private string _nonhyphenwords = "";

        public Search()
            : this(new EntitiesProvider())
        {
        }

        private Search(IEntitiesProvider entitiesProvider)
        {
            _entities = entitiesProvider.GetEntityContext();
        }
        #endregion

        private string Hyphenwords
        {
            get { return _hyphenwords; }
            set { _hyphenwords = GetHyphenwords(value); }
        }

        private string NonHyphenwords
        {
            get { return _nonhyphenwords; }
            set { _nonhyphenwords = GetNonHyphenwords(value); }
        }

        private static string ReplaceEx(string original,
                                        string pattern, string replacement)
        {
            int position0, position1;
            int count = position0 = 0;
            string upperString = original.ToUpper();
            string upperPattern = pattern.ToUpper();
            int inc = (original.Length / pattern.Length) *
                      (replacement.Length - pattern.Length);
            var chars = new char[original.Length + Math.Max(0, inc)];
            while ((position1 = upperString.IndexOf(upperPattern,
                                                    position0)) != -1)
            {
                for (int i = position0; i < position1; ++i)
                    chars[count++] = original[i];
                for (int i = 0; i < replacement.Length; ++i)
                    chars[count++] = replacement[i];
                position0 = position1 + pattern.Length;
            }
            if (position0 == 0) return original;
            for (int i = position0; i < original.Length; ++i)
                chars[count++] = original[i];
            return new string(chars, 0, count);
        }

        private static string FormatBody(string text)
        {
            string tmp = Regex.Replace(text, @"<(.|\n)*?>", string.Empty);
            int pos = tmp.ToLower().IndexOf(_term.ToLower());
            int ttllen = tmp.Length;
            int end;
            //if 150 chars in front of occurance is past then start at 0
            if (pos - 150 < 0)
            {
                pos = 0;
                end = tmp.Length < 300 ? tmp.Length : 300;
            }
            else
            {
                //set the start point to 150 before occurance
                pos = pos - 150;
                end = 300;
                if (pos + 300 > ttllen)
                {
                    end = (pos - ttllen) * -1;
                }
            }

            if (tmp.Length > 300)
            {
                tmp = tmp.Substring(pos, end);
            }
            tmp = ReplaceEx(tmp, _term, "<b>" + _term + "</b>");
            return tmp;
        }

        public IList<DTOSearchResult> GetResults(string term, bool usefulltext, Portal portal)
        {
            SearchLog itemToLog = new SearchLog();
            itemToLog.SearchTerm = term;
            itemToLog.AddedDate = DateTime.Now;
            itemToLog.PortalName = portal.Name;
            _entities.SearchLog.AddObject(itemToLog);
            _entities.SaveChanges();

            term = term.Replace("'", "");
            _term = term;
            Hyphenwords = term;
            NonHyphenwords = term;
            string sHyphenwords = Hyphenwords;
            string sNonHyphenwords = NonHyphenwords;

            var resultsToReturn = new List<DTOSearchResult>();
            //this is free in postgres so use it
            //if (usefulltext)
            //{
                DbCommand command = _entities.CreateStoreCommand("SearchMvcCms",
                         CommandType.StoredProcedure,
                     new PgSqlParameter("_SearchTerm", "'" + sNonHyphenwords + "'"),
                     new PgSqlParameter("_PortalID", portal.PortalID),
                     new PgSqlParameter("_Hyphenwords", "'" + sHyphenwords + "'")
                    );
                using (command.Connection.CreateConnectionScope())
                {                  
                    using (DbDataReader reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                           var newResult =  new DTOSearchResult
                              {
                                  ContentPageID = reader.Field<int>("contentpageid"),
                                  Title = TextInfo.ToTitleCase(reader["title"].ToString()),
                                  Body = FormatBody(reader.Field<string>("body")),
                                  UpdateDate = reader.Field<DateTime>("updatedate"),
                                  Path = reader.Field<string>("path"),
                                  CatPath = reader.Field<string>("catpath"),
                                  CatTitle = reader.Field<string>("cattitle"),
                                  IsCategoryPage = reader.Field<bool?>("iscategorypage").GetValueOrDefault(),
                                  IsSubPage = reader.Field<bool?>("issubpage").GetValueOrDefault(),
                                  IsForumResult = reader.Field<bool>("isforumresult"),
                                  IsWikiResult = reader.Field<bool>("iswikiresult"),
                                  Rank = (decimal)reader.Field<Single>("matchqual")
                              };
                           resultsToReturn.Add(newResult);
                        }
 
                    }                    
                }
                return resultsToReturn;
            //}
            //else
            //{
            //    DbCommand command = _entities.CreateStoreCommand("SearchMvcCms-NFT",
            //         CommandType.StoredProcedure,
            //         new PgSqlParameter("SearchTerm", term),
            //         new PgSqlParameter("PortalID", portal.PortalID)
            //        );
            //    return SSearchMaterializer
            //        .Materialize(command)
            //        ;
            //}
        }

        private static string GetNonHyphenwords(string value)
        {
            string result = "";
            Array aSkw = value.Split(' ');

            foreach (string part in aSkw)
            {
                //if part has a hyphen in it then add it to result
                if (!part.Contains("-"))
                {
                    result += part + " ";
                }
            }
            if ((result.Length > 0))
            {
                result = result.Substring(0, result.LastIndexOf(" "));
            }

            return result;
        }

        private static string GetHyphenwords(string value)
        {
            string result = "";
            Array aSkw = value.Split(' ');

            foreach (string part in aSkw)
            {
                //if part has a hyphen in it then add it to result
                if (part.Contains("-"))
                {
                    result += part + " ";
                }
            }
            if ((result.Length > 0))
            {
                result = result.Substring(0, result.LastIndexOf(" "));
            }

            return result;
        }


    }
}